package datapackage

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"shqsoft.cn/pasnj/base"
	"strings"
	"sync"
)

//Table 表，对用于关系数据库中的表
type Table struct {
	ID         int    `xml:"id,attr"`
	Name       string `xml:"name,attr"`
	Type       string `xml:"type,attr"`
	PrimaryKey string `xml:"primaryKey,attr"`
}

//DataPackage 数据包
type DataPackage struct {
	XMLName      xml.Name `xml:"DataPackage"`
	Name         string
	Description  string
	DataSource   string
	Dimensions   []Dimension   `xml:"Dimension"`
	VirtualCubes []VirtualCube `xml:"VirtualCube"`
	Cubes        []Cube        `xml:"Cube"`
	Relations    []Relation    `xml:"Relation"`
}

//newDataPackage 创建数据包
func newDataPackage(name string) (dp *DataPackage, err error) {
	path, err := base.ExecPath()
	if err != nil {
		return nil, err
	}
	var filePath string
	for _, dp := range base.Context.DataPackages {
		if dp.Name == name {
			filePath = dp.Path
			break
		}
	}
	if filePath == "" {
		return nil, fmt.Errorf("数据包%s在web.xml的定义中没有找到！", name)
	}
	xmlBytes, err := ioutil.ReadFile(path + "/" + filePath)
	if err == nil {
		dp = new(DataPackage)
		if err := xml.Unmarshal(xmlBytes, dp); err != nil {
			return nil, err
		}
		return dp, nil
	}
	return nil, err
}

var dpsMu sync.RWMutex
var dps []*DataPackage

//GetDataPackage 获取数据包定义
func GetDataPackage(name string) (dp *DataPackage, err error) {
	dpsMu.Lock()
	defer dpsMu.Unlock()
	for _, dp := range dps {
		if dp.Name == name {
			return dp, nil
		}
	}
	dp, err = newDataPackage(name)
	if err != nil {
		return nil, err
	}
	if dps == nil {
		dps = make([]*DataPackage, 0, 5)
	}
	for _, cube := range dp.Cubes {
		mLen := len(cube.Measures)
		for i := 0; i < mLen; i++ {
			mea := &cube.Measures[i]
			mea.Column = strings.ToUpper(mea.Column)
		}
	}
	for _, dim := range dp.Dimensions {
		hLen := len(dim.Hierarchies)
		for i := 0; i < hLen; i++ {
			hie := &dim.Hierarchies[i]
			hie.PrimaryKey = strings.ToUpper(hie.PrimaryKey)
			lLen := len(hie.Levels)
			for j := 0; j < lLen; j++ {
				lev := &hie.Levels[j]
				lev.Column = strings.ToUpper(lev.Column)
				lev.NameColumn = strings.ToUpper(lev.NameColumn)
				lev.OrderColumn = strings.ToUpper(lev.OrderColumn)
				lev.ParentColumn = strings.ToUpper(lev.ParentColumn)
				pLen := len(lev.Properties)
				for k := 0; k < pLen; k++ {
					pro := &lev.Properties[k]
					pro.Column = strings.ToUpper(pro.Column)
				}
			}
		}
	}
	dps = append(dps, dp)
	return dp, nil
}

//GetDimension 根据名称获取维度
func (dp *DataPackage) GetDimension(name string) (*Dimension, error) {
	for _, dim := range dp.Dimensions {
		if dim.Name == name {
			return &dim, nil
		}
	}
	errInfo := fmt.Sprintf("数据包%s中没有找到维度%s!", dp.Name, name)
	return nil, errors.New(errInfo)
}

//GetTimeDimension 获取时间维度
func (dp *DataPackage) GetTimeDimension() (*Dimension, error) {
	for _, dim := range dp.Dimensions {
		if dim.Type == "TimeDimension" {
			return &dim, nil
		}
	}
	return nil, errors.New("数据包中没有找到时间维度！")
}

//GetMeasure 根据指定的cubeName和度量值名称获取度量值
func (dp *DataPackage) GetMeasure(cubeName string, meaName string) (*Measure, error) {
	for _, cube := range dp.Cubes {
		if cube.Name == cubeName {
			for _, mea := range cube.Measures {
				if mea.Name == meaName {
					return &mea, nil
				}
			}
		}
	}
	errInfo := fmt.Sprintf("数据包%s没有找到立方体%s的度量值%s!", dp.Name, cubeName, meaName)
	return nil, errors.New(errInfo)
}

//DefaultDP 默认的数据包
var DefaultDP *DataPackage

func init() {
	if len(base.Context.DataPackages) == 0 {
		log.Panic("数据包没有定义!")
	}
	firstName := base.Context.DataPackages[0].Name
	ddp, err := GetDataPackage(firstName)
	if err != nil {
		log.Panicf("数据包%s加载数据包出错！%s", firstName, err)
	}
	DefaultDP = ddp
}
